/*
 * Copyright 2012-2013 Finbudget.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package finbudget.client.ui.widget.upload;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.http.client.UrlBuilder;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasEnabled;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

import finbudget.client.ui.widget.upload.UploadLine.UploadLineContainer;
import finbudget.client.ui.widget.upload.UploadLine.UploadLineFactory;
import finbudget.shared.Constants;

public class UploadWidget extends Composite implements HasEnabled, UploadLineContainer {
	/**
	 * The linesSeparator defines a symbol which separates lines values in a string
	 * representation of the widget value.
	 */
	public final static String linesSeparator = " ";
	/**
	 * The partsSeparator separates parts of values in the string value of a single UploadLine.
	 */
	public final static String partsSeparator = ";";
	interface Binder extends UiBinder<Widget, UploadWidget> {
	}
	private static final Binder binder = GWT.create(Binder.class);
	public interface UploadWidgetFactory {
		public UploadWidget create(UploadWidgetParams params);
	}
	// vlak, 2011-09-25 This class is just a workaround of a strange bug. In case I use 
	//		@Inject
	//		protected UploadWidget(UploadLineFactory uploadLineFactory, @Assisted String noNodeError, @Assisted keyNode, @Assisted value)
	// and pass string values to uploadWidgetFactory.create then all strings are arriving the same as noNodeError string! To bypass this
	// the new structure introduced.
	public static class UploadWidgetParams {
		public String placeholder;
		public String noNodeError;
		public String noItemsMessage;
		public String keyNode;
		public String value;
		public boolean readonly;
	}

	interface UploadWidgetStyle extends CssResource {
		String placeholderstyle();
	}

	@UiField UploadWidgetStyle style;
	@UiField Label placeholder;
	@UiField VerticalPanel panel;
	@UiField Label labelSaveBefore;
	@UiField Label labelNoItems;

	private final UploadLineFactory uploadLineFactory;
	private final String keyNode;
	private final List<UploadLine> lines;
	private final UploadWidgetParams params;

	@Inject
	protected UploadWidget(UploadLineFactory uploadLineFactory, @Assisted UploadWidgetParams params) {
		initWidget(binder.createAndBindUi(this));

		this.uploadLineFactory = uploadLineFactory;
		this.keyNode = params.keyNode;
		this.lines = new ArrayList<UploadLine>();
		this.params = params;

		placeholder.setText(params.placeholder);
		placeholder.addStyleName(style.placeholderstyle());
		panel.setWidth("100%");
		labelSaveBefore.setVisible(false);
		labelNoItems.setVisible(false);
		createLines(params.readonly, params.value, params.noNodeError, params.noItemsMessage);
	}

	private void addLine(boolean readonly, String lineValue) {
		UploadLine uploadLine = uploadLineFactory.create(keyNode, readonly, new Attachment(lineValue), this);
		lines.add(uploadLine);
		panel.add(uploadLine);
	}

	@Override
	public boolean isEnabled() {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void setEnabled(boolean enabled) {
		for (UploadLine line : lines) {
			line.setEnabled(enabled);
		}
	}

	public String getStringValue() {
		String value = "";
		for (UploadLine line : lines) {
			String lineValue = line.getStringValue();
			if (lineValue != null) {
				value += linesSeparator + lineValue;
			}
		}
		return value.trim().isEmpty() ? null : value;
	}

	private void createLines(boolean readonly, String value, String noNodeError, String noItemsMessage) {
		boolean isItemsAdded = false;
		if (value != null) {
			String[] values = value.split(linesSeparator);
			if (values != null) {
				for (String item : values) {
					if (!item.trim().isEmpty()) {
						addLine(readonly, item);
						isItemsAdded = true;
					}
				}
			}
		}
		if (!isItemsAdded && noItemsMessage != null) {
			labelNoItems.setText(noItemsMessage);
			labelNoItems.setVisible(true);
		}
		if (keyNode == null) {
			if (noNodeError != null) {
				labelSaveBefore.setText(noNodeError);
				labelSaveBefore.setVisible(true);
				labelNoItems.setVisible(false);
			}
		} else {
			// Allow to add new attachments just in case the keyNode is set.
			addLine(readonly, null);
			labelNoItems.setVisible(false);
		}
		showPlaceholderIfNeeded();
	}

	@Override
	public void createNewLine() {
		addLine(false, null);
		showPlaceholderIfNeeded();
	}

	/**
	 * Checks if any upload/ delete operation is in procees
	 * @return true in case no operations in process; 
	 * false is case there is at least one unfinished upload/ delete operation.
	 */
	public boolean canClose() {
		// TODO
		return true;
	}

	/**
	 * Terminates all (if any) upload/ delete requests.
	 */
	public void terminate() {
		// TODO
	}

	@Override
	public void onUploadComplete(UploadLine uploadLine, boolean success) {
		// Do nothing
	}

	private void showPlaceholderIfNeeded() {
		String text = placeholder.getText();
		if (text == null || text.trim().isEmpty()) {
			// Empty placeholder is not shown in any case.
			placeholder.setVisible(false);
		} else {
			placeholder.setVisible(lines.size() <= 1);
		}
	}

	public void recreateLines(String value) {
		for (UploadLine line : lines) {
			line.cleanup();
		}
		lines.clear();
		panel.clear();
		createLines(params.readonly, value, params.noNodeError, params.noItemsMessage);
	}

	public static String getUrlToDownloadFirstFileFromAttachmentFieldValue(String value) {
		if (value != null) {
			// Separate lines
			String[] values = value.split(linesSeparator);
			if (values != null) {
				for (int i = 0; i < values.length; i++) {
					Attachment attachment = new Attachment(values[i]);
					if (attachment.getBlobKey() != null && !attachment.getBlobKey().trim().isEmpty()) {
						UrlBuilder builder = Window.Location.createUrlBuilder();
						builder = builder.setPath(Constants.urlDownload);
						builder = builder.setHash(null);
						builder = builder.setParameter(Constants.paramBlob, attachment.getBlobKey());
						return builder.buildString();
					}
				}
			}
		}
		return null;
	}
}
